package main

import (
	"fmt"
	"net"
	"sync"
	"time"
)

type Server struct {
	Ip string
	Port int

	OnlineMap map[string]*User // 当前在线用户的map集合
	syncMap sync.Mutex

	RoomMap map[string][]*User // 房间群聊

	msgChan chan string // 往server里群发消息的
}

func NewServer(Ip string, Port int) *Server {

	server := &Server{
		Ip : Ip,
		Port: Port,
		OnlineMap: make(map[string]*User),
		syncMap: sync.Mutex{},
		RoomMap: make(map[string][]*User),
		msgChan: make(chan string),
	}

	return server
}

// 清除用户的信息
func (s *Server) clearUserInfoByName(user *User) {
	s.syncMap.Lock()
	delete(s.OnlineMap, user.Name)
	s.syncMap.Unlock()
}

// 监听message的goruntime
func (s *Server) ListenMessage()  {
	for {
		msgStr := <- s.msgChan
		s.syncMap.Lock()
		for _,cli := range s.OnlineMap {
			cli.C <- msgStr
		}
		s.syncMap.Unlock()
	}
}

// 广播
func (s *Server) BroadCast(strMsg string, fromUser *User){

	sendMsg := "[" + fromUser.AddrName + "]" + strMsg
	s.msgChan <- sendMsg
}


func (s *Server) Start()  {

	server,err := net.Listen("tcp", fmt.Sprintf("%s:%d", s.Ip, s.Port))

	if err != nil {
		fmt.Println(err)
		panic("net.Dial error ")
	}

	fmt.Sprintf("go-im已启动:%d", s.Port)
	defer server.Close()

	time.Sleep(1 * time.Second)
	//启动监听Message的goroutine
	go s.ListenMessage()

	for  {
		conn, err := server.Accept()
		if err != nil {
			fmt.Println("accept has err: ", err)
			continue
		}

		// 另起一个go runtime， 处理用户和服务端交互的信息
		go s.Handler(conn)
	}
}

func (s *Server)Handler(conn net.Conn)  {

	// 保存用户信息至Server.OnlineMap中
	user := NewUser(conn, s)

	s.syncMap.Lock()
	s.OnlineMap[user.Name] = user
	s.syncMap.Unlock()

	// 监听user管道里是否来信息
	go user.listenMsg()

	// 上线通知
	user.Online()

	// 开个goruntime 处理客户端发来的信息
	go user.Handler()

	/**
		超时踢下线
		1. 用户在线超过10s未发言，踢下线
	 */

	for {
		select {
		case <- user.Live:
			// 收到消息

		case <- time.After(300 * time.Second):
			// 下线用户
			user.SendMsg("你被提了！")

			//销毁用的资源
			close(user.C)

			//关闭连接
			conn.Close()

			//退出当前Handler
			return //runtime.Goexit()
		}
	}
}